#ifndef VSLOGIC_H
#define VSLOGIC_H

#include "vsGlobal.h"
#include "io/vsServer.h"

class vsMediaFile;
class QTimer;
class QFileSystemWatcher;

//--------------------------------------------------------------------------
// view
//--------------------------------------------------------------------------
class vsUI : public QObject
{
    Q_OBJECT

public:
    explicit vsUI(QObject *other = 0);
    ~vsUI();

    // callback from logic after setting up all connections, must be called once
    virtual void onConnected() = 0;

    // calls UI for rearranged order of medias to save & restore on next launch
    virtual QStringList getIdOrder() const = 0;

public slots:
    void onFileAdded(vsMediaFile*) {}
    void onFileRemoved(QString) {}
    void onMediaIDChanged(QString,vsMediaFile*) {}
    void onNetworkInfoUpdated(QString /*id*/, int /*requests*/, int /*uprate*/, int /*dlrate*/, qint64 /*seeded*/) {}

    void watchFolder(const QString &/*path*/) {}  // received from logic, must show it in UI
    void stopWatchingFolder(const QString &/*path*/) {}

signals:
    void addFile(QString name, QString params);
    void exiting(); /// request to exit the application

    void portChanged(int);
    void fwScanIntervalChanged(int);
    void urlEdited(QString);

    void mediaIDChanged(QString, QString);  // transmitted to logic, it'll call onMediaIDChanged on success
    void removeMedia(QString);              // transmitted to logic, it'll call onFileRemoved on success

    void watchedFolderAdded(QString);
    void watchedFolderRemoved(QString);

protected:
    bool initialized;

private:
    Q_DISABLE_COPY(vsUI)
};


//--------------------------------------------------------------------------
// app controller that assembles file and network operations with user interfaces
//--------------------------------------------------------------------------
class vsLogic : public QObject, public vsInfoController
{
    Q_OBJECT

public:
    explicit vsLogic(QObject *parent = 0);
    ~vsLogic();

    bool connectUI(vsUI *ui);

    bool canServeID(QString id)              override;
    bool getMediaInfo(vsNetworkMediaInfo &i) override;

public slots:
    void onAddFile(const QString &path, QString params);
    void addMediasFromPath(const QString &path);

    void onAppMessage(const QString&); // interprocess communication
    void onExit();

    void onNetworkInfo(QString path, qint64 bytesSent);

    void onPortChange(int);
    void onURLEdited(QString);

    void onMediaIDChanged(QString oldID, QString newID); // signal from ui, params are old id and new id
    void onRemoveMedia(QString id); // signal from ui, param is id

    void onWatchFolder(const QString &path);
    void onStopWatchingFolder(const QString &path);

private slots:
    void netInfoTimer();
    void folderWatchTimer();
    void onWatchedFileChanged(QString);

signals:
    void fileAdded(vsMediaFile*);
    void networkInfoUpdated(QString id, int requests, int uprate, int dlrate, qint64 seeded);

    void mediaIDChanged(QString, vsMediaFile*);
    void mediaRemoved(QString);

    void watchingFolder(QString);
    void stoppedWatchingFolder(QString);

protected:
    bool ffprobe_available;
    bool ffmpeg_available;

    QLinkedList<vsMediaFile*>   files;
    QMap<QString, vsMediaFile*> filesMap; // by id
    QMap<QString, vsMediaFile*> filepathsMap; // by filepath

    QMap<QString, bool> watchedFolders;
    QFileSystemWatcher *fsWatcher    = 0;
    QTimer             *fsWatchTimer = 0;

    QString generateLocalID();

    vsServer *network;

    struct vsFileNetworkStats
    {
        qint64 requests;
        qint64 uprate;
        qint64 dlrate;
        qint64 totalSeeded;
        bool   active;

        byterateCounter bps;

        vsFileNetworkStats() : requests(0), uprate(0), dlrate(0), totalSeeded(0), active(false) {}
    };

    QMap<QString, vsFileNetworkStats> netstats; // id as key


private:
    Q_DISABLE_COPY(vsLogic)
};


#endif // VSLOGIC_H
